package io.itit.ecp.admin.server.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import icu.mhb.mybatisplus.plugln.base.service.impl.JoinServiceImpl;
import io.itit.ecp.admin.server.entity.CarbonSinkDataEntity;
import io.itit.ecp.admin.server.entity.extend.CarbonSinkDataExtEntity;
import io.itit.ecp.admin.server.mapper.CarbonSinkDataMapper;
import io.itit.ecp.admin.server.service.ICarbonSinkDataService;
import io.itit.grass.common.server.dto.ParamDto;
import io.itit.grass.common.utils.Y666Utils;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;

/**
 * <p>
 *
 * @Author：Roy
 * @Description：碳汇数据服务实现类
 * @Date：Create by 2023-12-01 10:45:08
 */
@Service
public class CarbonSinkDataServiceImpl extends JoinServiceImpl<CarbonSinkDataMapper, CarbonSinkDataEntity> implements ICarbonSinkDataService {

    @Override
    public CarbonSinkDataExtEntity sum(ParamDto dto) {
        return Optional.ofNullable(baseMapper.sum(dto)).orElse(new CarbonSinkDataExtEntity());
    }

    @Override
    public List<CarbonSinkDataExtEntity> sumGroupType(ParamDto dto) {
        return baseMapper.sumGroupType(dto);
    }

    @Override
    public List<CarbonSinkDataExtEntity> sumGroupSolidifyDate(ParamDto dto) {
        return baseMapper.sumGroupSolidifyDate(dto);
    }

    @Override
    public List<CarbonSinkDataExtEntity> sumGroupSolidifyDateAndType(ParamDto dto) {
        return baseMapper.sumGroupSolidifyDateAndType(dto);
    }

    @Override
    @Transactional
    public boolean causeFactorUpdate(String type, Date solidifyDate, BigDecimal factor) {
        List<CarbonSinkDataEntity> entityList = this.lambdaQuery()
                .ge(CarbonSinkDataEntity::getSolidifyDate, DateUtil.beginOfMonth(solidifyDate))
                .le(CarbonSinkDataEntity::getSolidifyDate, DateUtil.endOfMonth(solidifyDate))
                .eq(CarbonSinkDataEntity::getType, type)
                .list();
        if (CollectionUtils.isNotEmpty(entityList)) {
            // 重新计算碳汇数据的值
            BigDecimal ra = new BigDecimal(365);
            entityList.forEach(entity -> calcDay(ra, entity.getArea(), factor, entity));
            return updateBatchById(entityList);
        }
        return true;
    }

    private void calcDay(BigDecimal ra, BigDecimal area, BigDecimal factor, CarbonSinkDataEntity entity) {
        BigDecimal multiply = Y666Utils.multiply(area, factor);
        BigDecimal divide = Y666Utils.divide(multiply, ra, 8);
        entity.setCarbonEmission(divide);
        entity.setCarbonEmissionProcess(area + "*" + factor + "/" + ra);
    }

    @Override
    public BigDecimal computeCarbonReductionTotal(String sceneProjectId, String sceneEdificeId, String sceneFloorId, LocalDateTime start, LocalDateTime end) {
        return this.computeCarbonReductionTotal(sceneProjectId, sceneEdificeId, sceneFloorId,
                Objects.isNull(start) ? null : Date.from(start.atZone(ZoneId.systemDefault()).toInstant()),
                Objects.isNull(end) ? null : Date.from(end.atZone(ZoneId.systemDefault()).toInstant()));
    }

    @Override
    public BigDecimal computeCarbonReductionTotal(String sceneProjectId, String sceneEdificeId, String sceneFloorId, Date start, Date end) {
        List<Map<String, Object>> list = baseMapper.selectMaps(new QueryWrapper<CarbonSinkDataEntity>()
                .select("SUM(carbon_emission) as carbonEmission")
                .eq(StringUtils.hasLength(sceneProjectId), "scene_project_id", sceneProjectId)
                .eq(StringUtils.hasLength(sceneEdificeId), "scene_edifice_id", sceneEdificeId)
                .eq(StringUtils.hasLength(sceneFloorId), "scene_floor_id", sceneFloorId)
                .ge(Objects.nonNull(start), "solidify_date", start)
                .le(Objects.nonNull(end), "solidify_date", end)
        );
        BigDecimal result = BigDecimal.ZERO; //  能源使用总量
        if (!list.isEmpty()) {
            Map<String, Object> map = list.get(0);
            Object standardCoal = Objects.isNull(map) ? null : map.get("carbonEmission"); // 碳汇总量
            if (Objects.nonNull(standardCoal)) {
                result = new BigDecimal(standardCoal.toString());
            }
        }
        return result.setScale(2, RoundingMode.HALF_DOWN);
    }
}